const { Client } = require('@elastic/elasticsearch')
const config = require('config')
const es_config = config.get('elasticsearch')
const client = new Client({
    node: `http://${es_config.host || 'localhost'}:${es_config.port || '9200'}`
})
const index = 'lnkg'

const initMapping = async ()=>{
    const ik_mapping = {
        "type": "text",
        "analyzer": "ik_max_word",
        "search_analyzer": "ik_smart"
    },
    keyword_mapping = {
        "type": "keyword"
    },
    text_mapping = {
        "type": "text"
    }
    let dynamic_templates = [
        {
            "as_text": {
                "match_pattern": "regex",
                "match": ".*text$|.*label$|.*title$",
                "mapping": es_config.useIkAnalysis ? ik_mapping : text_mapping
            }
        },
        {
            "as_date": {
                "match_pattern": "regex",
                "match": ".*_date$|.*_Date$",
                "mapping": {
                    "type": "date"
                }
            }
        },
        {
            "as_keyword": {
                "match_mapping_type": "string",
                "match": "*",
                "mapping": keyword_mapping
            }
        }
    ]
    await client.indices.putMapping({
        index,
        body:{
            dynamic_templates
        }
    })
    console.log('add mapping in elasticsearch success')
}

const init = async (force) => {
    let exist = await client.indices.exists({
        index: index,
    })
    if(exist&&exist.statusCode==404){
        await client.indices.create({
            index
        })
    }else{
        if(force){
            await client.indices.delete({
                index: index,
            })
            await client.indices.create({
                index
            })
        }
    }
    await initMapping()
}

const save = async (data)=>{
    let saveObj = {
        index: index,
        type: '_doc',
        body: {...data,createDate:Date.now()},
        refresh:true
    }
    if(data.id){
        saveObj.id = data.id
    }
    await client.index(saveObj)
}

const retrieve = async (params)=>{
    let query = params.id?`_id:${params.id}`:(params.keyword?params.keyword:'*')
    let queryObj = params.body?{body:params.body}:{q:query}
    let _source = params.source?params.source:true;
    params.from = params.from||0
    params.size = params.size||1000
    let params_pagination = {"from":params.from,"size":params.size}
    if(params.body&&params.body.aggs){
        params_pagination = {size:0}
        params.aggs = true
    }
    let searchObj = Object.assign({
        index: index,
        _source:_source
    },queryObj,params_pagination)
    let result = await client.search(searchObj)
    if(params.aggs){
        result = {count:result.body.hits.total.value||result.body.hits.total,aggs:result.body.aggregations}
    }else{
        result =  {count:result.body.hits.total.value,results:result.body.hits.hits.map((result)=>result._source)}
    }
    return result
}

const batchSave = async (items)=>{
    let bulks = [],bulk_action,bulk_obj
    for (let item of items) {
        bulk_obj = item
        bulk_action = {_index: index,_type:'_doc'}
        if(item.id){
            bulk_action._id = item.id
        }
        bulks.push({index:bulk_action})
        bulks.push(bulk_obj)
    }
    return await client.bulk({body:bulks,refresh:true})
}

const del = async ()=>{
    await client.indices.delete({
        index: index,
    })
}

module.exports = {init,save,retrieve,batchSave,del}
